import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np


def build_data(file_path):
    """
    加载数据
    :param file_path:数据路径
    :return: air_data
    """
    air_data = pd.read_csv(file_path, encoding='ANSI')
    return air_data


def deal_data(air_data):
    """
    数据处理
    :param air_data: 航空原始数据
    :return: 处理之后的数据
    """
    # 根据具体业务法---处理缺失、异常值
    # a、丢弃票价为空的记录。
    bool_index_1 = air_data['SUM_YR_1'].notnull()
    bool_index_2 = air_data['SUM_YR_2'].notnull()
    bool_index = bool_index_1 & bool_index_2  # 两个同时满足True
    # b、丢弃票价为0
    air_data = air_data.loc[bool_index, :]

    # b、丢弃票价为0、平均折扣率不为0、总飞行千米数大于0的记录。
    # 　票价大于0
    bool_id_1 = air_data['SUM_YR_1'] > 0
    bool_id_2 = air_data['SUM_YR_2'] > 0
    # 折扣大于0
    bool_id_3 = air_data['avg_discount'] > 0
    # 飞行里程大于0
    bool_id_4 = air_data['SEG_KM_SUM'] > 0
    # b、丢弃票价为0、平均折扣率不为0、总飞行千米数大于0的记录。
    bool_id = (bool_id_1 | bool_id_2) & bool_id_3 & bool_id_4

    air_data = air_data.loc[bool_id, :]

    # 3、LRMFC ---筛选，构建
    # L ----> 入会时间 到窗口结束的月数
    # R ----> 最后一次乘坐飞机距离窗口结束的月数
    # F ----> 乘坐飞机的次数
    # M ----> 飞行里程
    # C ----> 折扣
    # 筛选出相关特征
    air_data = air_data.loc[:, [
                                   'FFP_DATE', 'LOAD_TIME',
                                   'LAST_TO_END',
                                   'FLIGHT_COUNT',
                                   'SEG_KM_SUM',
                                   'avg_discount'
                               ]
                            ]

    # 构建 L ----结束时间- 入会时间 --------> 转换为pandas 默认支持的数据类型
    air_data['L_days'] = pd.to_datetime(air_data['LOAD_TIME']) - pd.to_datetime(air_data['FFP_DATE'])
    # print(air_data['L_days'])
    air_data['L'] = [temp.days / 30 for temp in air_data['L_days']]

    # 构建R R ----> 最后一次乘坐飞机距离窗口结束的月数

    air_data['R'] = air_data['LAST_TO_END'] / 30  # 'LAST_TO_END' 是日
    # F ----> 乘坐飞机的次数
    air_data['F'] = air_data['FLIGHT_COUNT']
    # M - ---> 飞行里程
    air_data['M'] = air_data['SEG_KM_SUM']
    # C ----> 折扣
    air_data['C'] = air_data['avg_discount']

    air_data = air_data.loc[:, ['L', 'R', 'F', 'M', 'C']]
    # 4、标准化---剔除量级影响
    stand = StandardScaler()
    air_data = stand.fit_transform(air_data)

    return air_data


def k_means(air_data, k):
    """
    实现sklearn 中k_means进行航空用户聚类
    :param air_data: 数据
    :param k: 聚类数目
    :return:y_predict, center
    """
    # 实例化算法对象
    km = KMeans(n_clusters=k)
    # 训练数据并构建模型
    km.fit(air_data)
    # 预测
    y_predict = km.predict(air_data)
    center = km.cluster_centers_

    return y_predict, center


def show_res(center):
    """

    :param center:
    :return:
    """
    plt.figure()
    # 支持中文
    plt.rcParams['font.sans-serif'] = 'SimHei'
    # 支持负号
    plt.rcParams['axes.unicode_minus'] = False
    data_length = center.shape[1]

    angle = np.linspace(0, 2 * np.pi, data_length, endpoint=False)

    angle = np.concatenate((angle, [angle[0]]), axis=0)

    for i in range(center.shape[0]):
        data = np.concatenate((center[i, :], [center[i, 0]]), axis=0)
        plt.polar(angle, data)
    plt.title('航空用户聚类结果展示')
    plt.legend(['第一类用户', '第二类用户', '第三类用户', '第四类用户', '第五类用户'], loc=4)
    plt.xticks(angle[:-1], ['L', 'R', 'F', 'M', 'C'])
    plt.savefig('航空用户聚类结果展示')
    plt.show()


def main():
    """
    主函数
    :return: None
    """

    # 1、了解具体的航空业务
    # 竞争激烈 、 不同用户价值不同
    # 62988 条数据
    # 每一列----意义

    # 1、加载数据
    air_data = build_data('./air_data.csv')
    print(air_data.columns)
    # 2、数据处理
    air_data = deal_data(air_data)
    print(air_data)
    # 3、使用k_means算法
    k = 5
    y_predict, center = k_means(air_data, k)
    print(y_predict)
    # 4、聚类 center
    print(center)
    # 数据可视化
    show_res(center)
    # 7、分析可视化结果---不同的用户的价值
    # 8、根据不同价值的用户---不同的营销策略


if __name__ == '__main__':
    main()
